
stairs = {}

-- Load support for MT game translation.
local S = minetest.get_translator('stairs')


local function rotate_and_place(itemstack, placer, pointed_thing)
   local p0 = pointed_thing.under
   local p1 = pointed_thing.above
   local param2 = 0

   if placer then
      local placer_pos = placer:get_pos()
      if placer_pos then
         param2 = minetest.dir_to_facedir(vector.subtract(p1, placer_pos))
      end

      local finepos = minetest.pointed_thing_to_face_pos(placer, pointed_thing)
      local fpos = finepos.y % 1

      if p0.y - 1 == p1.y or (fpos > 0 and fpos < 0.5)
            or (fpos < -0.5 and fpos > -0.999999999) then
         param2 = param2 + 20
         if param2 == 21 then
            param2 = 23
         elseif param2 == 23 then
            param2 = 21
         end
      end
   end
   return minetest.item_place(itemstack, placer, pointed_thing, param2)
end

-- Register stair
-- Node will be called stairs:stair_<subname>

function stairs.register_stair(subname, groups, images, sounds, worldaligntex)
   -- Set backface culling and world-aligned textures
   local stair_images = {}
   for i, image in ipairs(images) do
      if type(image) == 'string' then
         stair_images[i] = {
            name = image,
            backface_culling = true,
         }
         if worldaligntex then
            stair_images[i].align_style = 'world'
         end
      else
         stair_images[i] = table.copy(image)
         if stair_images[i].backface_culling == nil then
            stair_images[i].backface_culling = true
         end
         if worldaligntex and stair_images[i].align_style == nil then
            stair_images[i].align_style = 'world'
         end
      end
   end
   local new_groups = table.copy(groups)
   new_groups.stair = 1
   minetest.register_node(':stairs:stair_' .. subname, {
      description = subname..' stair',
      drawtype = 'nodebox',
      tiles = stair_images,
      paramtype = 'light',
      paramtype2 = 'facedir',
      is_ground_content = false,
      groups = new_groups,
      sounds = sounds,
      node_box = {
         type = 'fixed',
         fixed = {
            {-0.5, -0.5, -0.5, 0.5, 0.0, 0.5},
            {-0.5, 0.0, 0.0, 0.5, 0.5, 0.5},
         },
      },
      on_place = function(itemstack, placer, pointed_thing)
         if pointed_thing.type ~= 'node' then
            return itemstack
         end

         return rotate_and_place(itemstack, placer, pointed_thing)
      end,
   })
end


-- Register slab
-- Node will be called stairs:slab_<subname>

function stairs.register_slab(subname, groups, images, sounds, worldaligntex)
   -- Set world-aligned textures
   local slab_images = {}
   for i, image in ipairs(images) do
      if type(image) == 'string' then
         slab_images[i] = {
            name = image,
         }
         if worldaligntex then
            slab_images[i].align_style = 'world'
         end
      else
         slab_images[i] = table.copy(image)
         if worldaligntex and image.align_style == nil then
            slab_images[i].align_style = 'world'
         end
      end
   end
   local new_groups = table.copy(groups)
   new_groups.slab = 1
   minetest.register_node(':stairs:slab_' .. subname, {
      description = subname..' slab',
      drawtype = 'nodebox',
      tiles = slab_images,
      paramtype = 'light',
      paramtype2 = 'facedir',
      is_ground_content = false,
      groups = new_groups,
      sounds = sounds,
      node_box = {
         type = 'fixed',
         fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5},
      },
      on_place = function(itemstack, placer, pointed_thing)
         local under = minetest.get_node(pointed_thing.under)
         local wield_item = itemstack:get_name()
         local player_name = placer and placer:get_player_name() or ''
         local creative_enabled = (creative and creative.is_enabled_for
               and creative.is_enabled_for(player_name))

         if under and under.name:find('^stairs:slab_') then
            -- place slab using under node orientation
            local dir = minetest.dir_to_facedir(vector.subtract(
               pointed_thing.above, pointed_thing.under), true)

            local p2 = under.param2

            -- Placing a slab on an upside down slab should make it right-side up.
            if p2 >= 20 and dir == 8 then
               p2 = p2 - 20
            -- same for the opposite case: slab below normal slab
            elseif p2 <= 3 and dir == 4 then
               p2 = p2 + 20
            end

            -- else attempt to place node with proper param2
            minetest.item_place_node(ItemStack(wield_item), placer, pointed_thing, p2)
            if not creative_enabled then
               itemstack:take_item()
            end
            return itemstack
         else
            return rotate_and_place(itemstack, placer, pointed_thing)
         end
      end,
   })
end

-- Register inner stair
-- Node will be called stairs:stair_inner_<subname>

function stairs.register_stair_inner(subname, groups, images, sounds, worldaligntex)
   -- Set backface culling and world-aligned textures
   local stair_images = {}
   for i, image in ipairs(images) do
      if type(image) == 'string' then
         stair_images[i] = {
            name = image,
            backface_culling = true,
         }
         if worldaligntex then
            stair_images[i].align_style = 'world'
         end
      else
         stair_images[i] = table.copy(image)
         if stair_images[i].backface_culling == nil then
            stair_images[i].backface_culling = true
         end
         if worldaligntex and stair_images[i].align_style == nil then
            stair_images[i].align_style = 'world'
         end
      end
   end
   local new_groups = table.copy(groups)
   new_groups.stair = 1
   minetest.register_node(':stairs:stair_inner_' .. subname, {
      description = subname..' inner stair',
      drawtype = 'nodebox',
      tiles = stair_images,
      paramtype = 'light',
      paramtype2 = 'facedir',
      is_ground_content = false,
      groups = new_groups,
      sounds = sounds,
      node_box = {
         type = 'fixed',
         fixed = {
            {-0.5, -0.5, -0.5, 0.5, 0.0, 0.5},
            {-0.5, 0.0, 0.0, 0.5, 0.5, 0.5},
            {-0.5, 0.0, -0.5, 0.0, 0.5, 0.0},
         },
      },
      on_place = function(itemstack, placer, pointed_thing)
         if pointed_thing.type ~= 'node' then
            return itemstack
         end

         return rotate_and_place(itemstack, placer, pointed_thing)
      end,
   })
end


-- Register outer stair
-- Node will be called stairs:stair_outer_<subname>

function stairs.register_stair_outer(subname, groups, images, sounds, worldaligntex)
   -- Set backface culling and world-aligned textures
   local stair_images = {}
   for i, image in ipairs(images) do
      if type(image) == 'string' then
         stair_images[i] = {
            name = image,
            backface_culling = true,
         }
         if worldaligntex then
            stair_images[i].align_style = 'world'
         end
      else
         stair_images[i] = table.copy(image)
         if stair_images[i].backface_culling == nil then
            stair_images[i].backface_culling = true
         end
         if worldaligntex and stair_images[i].align_style == nil then
            stair_images[i].align_style = 'world'
         end
      end
   end
   local new_groups = table.copy(groups)
   new_groups.stair = 1
   minetest.register_node(':stairs:stair_outer_' .. subname, {
      description = subname..' outer stair',
      drawtype = 'nodebox',
      tiles = stair_images,
      paramtype = 'light',
      paramtype2 = 'facedir',
      is_ground_content = false,
      groups = new_groups,
      sounds = sounds,
      node_box = {
         type = 'fixed',
         fixed = {
            {-0.5, -0.5, -0.5, 0.5, 0.0, 0.5},
            {-0.5, 0.0, 0.0, 0.0, 0.5, 0.5},
         },
      },
      on_place = function(itemstack, placer, pointed_thing)
         if pointed_thing.type ~= 'node' then
            return itemstack
         end

         return rotate_and_place(itemstack, placer, pointed_thing)
      end,
   })
end


-- Stair/slab registration function.
-- Nodes will be called stairs:{stair,slab}_<subname>

function stairs.register_stair_and_slab(subname, groups, images, sounds, worldaligntex)
   stairs.register_stair(subname, groups, images, sounds, worldaligntex)
   stairs.register_stair_inner(subname, groups, images, sounds, worldaligntex)
   stairs.register_stair_outer(subname, groups, images, sounds, worldaligntex)
   stairs.register_slab(subname, groups, images, sounds, worldaligntex)
end
